home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 7: Sunsite
/
Linux Cubed Series 7 - Sunsite Vol 1.iso
/
system
/
admin
/
linuxcon.000
/
linuxcon
/
linuxconf-1.6
/
translate
/
msgcomp.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-04-18
|
6KB
|
248 lines
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
#include "internal.h"
#ifdef UNIX
#define MAXIMUM_PATH PATH_MAX
#else
#define MAXIMUM_PATH 128
#endif
#define MISSING_MESSAGE "-???-"
/*
Print an error message in a popup
Stubs to avoid linking the world
*/
void xconf_error (const char *msg, ...)
{
va_list list;
va_start (list,msg);
vfprintf (stderr,msg,list);
va_end (list);
}
/* #Specification: translation / principle
The translation mecanism used by linuxconf is fairly
different from other system in used. Most system use
an external dictionary which can be translated without
recompiling the source. Linuxconf use a similar setup
except the dictionary is updated from the source.
First msgscan is used to produce/update dictionnaries by
scanning all source file. It looks for macros like
#
MSG_U(ID,"english message")
#
or already translated ones
#
MSG_B(ID,"english message","french message")
#
From that, it produce a dictionary.
This disctionary is then compiled and produce one include
file per dictionary and a resource message file which
contain several dictionary.
One program may very well used several
dictionary and a dictionary may be compiled in many
message resource file.
*/
static const char *msgcomp_getmsg (
TR_STRING *t,
const char *lang)
{
const char *ret = NULL;
while (*lang != '\0'){
ret = t->getmsg(lang[0]);
if (ret != NULL) break;
lang++;
}
return ret;
}
static const char *msgcomp_getmsg (
TR_STRING *t,
TR_STRINGS *trans, // Alternative dictionary to use
const char *lang,
const char *sysname) // Use to print error message
// If NULL, no error needed
{
const char *ret = NULL;
TR_STRING *tt = trans->getitem(t->getid());
if (tt != NULL) ret = msgcomp_getmsg (tt,lang);
if (ret == NULL) ret = msgcomp_getmsg(t,lang);
if (ret == NULL && sysname != NULL){
fprintf (stderr,"Missing message %s, system %s\n"
,t->getid(),sysname);
}
return ret;
}
class TR_STRINGS_COMP{
public:
TR_STRINGS ref; // Reference dictionary
TR_STRINGS trans; // Translation
/*~PROTOBEG~ TR_STRING_COMP */
/*~PROTOEND~ TR_STRING_COMP */
};
static int msgcomp_write (
const char *outfile,
TR_STRINGS_COMP trs[],
char *sysnames[],
int nbsys,
char *lang) // Language to generate
// Instead of being a letter, it is a string of
// letter. The first one is the prefered one
// the other are fallback if the first is missing
{
int ret = -1;
FILE *fout = fopen (outfile,"wb");
if (fout == NULL){
fprintf (stderr,"Can't open file %s (%s)\n"
,outfile,strerror(errno));
}else{
// We write the header
ret = 0;
BDICT_HEADER hd;
hd.magic = BDICT_MAGIC;
hd.version = BDICT_VERSION;
hd.nbsys = nbsys;
fwrite (&hd,sizeof(hd),1,fout);
long offset_msg = sizeof(hd);
// Then the header of each system
int i;
for (i=0; i<nbsys; i++){
TR_STRINGS_COMP *tr = trs + i;
BDICT_SYSTEM sys;
memset (&sys,0,sizeof(sys));
strcpy (sys.name,sysnames[i]);
sys.version = tr->ref.getversion();
sys.nbmsg = tr->ref.getnb();
fwrite (&sys,sizeof(sys),1,fout);
offset_msg += sizeof (BDICT_SYSTEM) + sys.nbmsg*sizeof(long);
}
// Then the lookup table for each system
// offset_msg now point to the beginning of the raw messages
// area
for (i=0; i<nbsys; i++){
TR_STRINGS_COMP *tr = trs + i;
int n = tr->ref.getnb();
TR_STRINGS *trans = &tr->trans;
for (int m=0; m<n; m++){
TR_STRING *t = tr->ref.getitem(m);
fwrite (&offset_msg,sizeof(offset_msg),1,fout);
const char *msg = msgcomp_getmsg (t,trans,lang
,sysnames[i]);
if (msg == NULL) msg = MISSING_MESSAGE;
char buf[10000];
str_compile (msg,buf);
offset_msg += strlen (buf)+1;
}
}
for (i=0; i<nbsys; i++){
TR_STRINGS_COMP *tr = trs + i;
int n = tr->ref.getnb();
TR_STRINGS *trans = &tr->trans;
for (int m=0; m<n; m++){
TR_STRING *t = tr->ref.getitem(m);
const char *msg = msgcomp_getmsg (t,trans,lang,NULL);
if (msg == NULL) msg = MISSING_MESSAGE;
char buf[10000];
str_compile (msg,buf);
int len = strlen (buf)+1;
fwrite (buf,len,1,fout);
}
}
fclose (fout);
}
return ret;
}
int main (int _argc, char *_argv[])
{
char *argv[200];
int argc = anlparm (_argc,_argv,argv);
int ret = -1;
if (argc < 4){
fprintf (stderr,"msgcomp -ppath [-ppath] resfile lang_select dictionary ...\n");
}else{
char **tbsys = (char**)malloc(argc*sizeof(char*));
ret = 0;
int a;
const char *paths[2];
paths[0] = paths[1] = "";
int nbpath = 0;
for (a=1; a<argc; a++){
char *arg = argv[a];
if (arg[0] == '-'){
if (arg[1] == 'p'){
if (nbpath == 2){
fprintf (stderr,"Option -p may be used only twice\n");
}else if (arg[2] == '\0'){
a++;
paths[nbpath++] = argv[a];
}else{
paths[nbpath++] = arg+2;
}
}else{
fprintf (stderr,"Invalid option %s\n",arg);
}
}else{
break;
}
}
const char *res = argv[a++];
char *lang = argv[a++];
TR_STRINGS_COMP *trs = new TR_STRINGS_COMP[argc];
for (int i=a; i<argc; i++){
char *syspath = argv[i];
TR_STRINGS_COMP *tr = trs + i - a;
char path[MAXIMUM_PATH];
sprintf (path,"%s%s.dic",paths[0],syspath);
printf ("Processing %s\n",path);
tr->ref.read (path);
char *pt = strrchr (syspath,'/');
if (pt != NULL) syspath = pt+1;
tbsys[i-a] = strdup(syspath);
if (tr->ref.getnb()==0){
fprintf (stderr,"Empty dictionary %s\n"
,argv[i]);
ret = -1;
}
if (nbpath == 2){
sprintf (path,"%s%s.dic",paths[1],argv[i]);
printf (" %s\n",path);
tr->trans.read (path);
}
}
if (ret != -1){
ret = msgcomp_write (res,trs,tbsys,argc-a,lang);
}else{
fprintf (stderr
,"**** There were some error(s)\n"
"**** No message produced\n");
}
}
return ret;
}